package com.dyb.nio.reactor;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 处理器
 * @author dyb
 * @date 2020/6/19
 */
public class IOHandle implements Runnable {
    SocketChannel socketChannel;
    static final int RECEIVEING = 0, SENDING = 1;
    volatile int state = RECEIVEING;
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    SelectionKey selectionKey;

    static ExecutorService pool = Executors.newFixedThreadPool(4);

    IOHandle (SocketChannel socketChannel, Selector selector) throws IOException {
        this.socketChannel = socketChannel;
        socketChannel.configureBlocking(false);
        // 后绑定监听事件
        selectionKey = socketChannel.register(selector, 0);

        selectionKey.interestOps(SelectionKey.OP_READ);
        selectionKey.attach(this);
    }

    @Override
    public void run() {
        // 交给线程池异步执行
        pool.execute(new AsyncTask());
    }

    private synchronized void asyncTask() {
        if (state == RECEIVEING) {
            try {
                int length = 0;
                // System.out.println(Thread.currentThread().getName()+ " receive：");
                while ((length = socketChannel.read(byteBuffer)) > 0) {
                    System.out.println("\t" + new String(byteBuffer.array(), 0, length));
                }
                byteBuffer.flip();
                selectionKey.interestOps(SelectionKey.OP_WRITE);
                state = SENDING;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if (state == SENDING) {
            try {
                // System.out.println(Thread.currentThread().getName()+ " send：");
                if (byteBuffer.limit() > 0) {
                    System.out.println("\t" + new String(byteBuffer.array(), 0, byteBuffer.limit()));
                }
                socketChannel.write(byteBuffer);
                byteBuffer.clear();
                selectionKey.interestOps(SelectionKey.OP_READ);
                state = RECEIVEING;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    class AsyncTask implements Runnable {
        @Override
        public void run() {
            IOHandle.this.asyncTask();
        }
    }
}
